// Window.cpp
//

#include <coedef.h>
#include "Window.h"
#include "Utilities.h"
#include "Log.h"
#include "LOCKSERVER.mbg"

_LIT(KMBMFileName,"LockServer.mbm");

/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////// CWsClient implementation ////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////

CWsClient* CWsClient::NewL(const TRect& aRect)
{
	// make new client
	CWsClient* client=new (ELeave) CWsClient(aRect); 
	CleanupStack::PushL(client);	// push, just in case
	client->ConstructL();			// construct and run
	CleanupStack::Pop();
	return client;
}

CWsClient::CWsClient(const TRect& aRect)
	: CActive(CActive::EPriorityHigh),
	iRect(aRect)
{	
}

void CWsClient::ConstructL()
{
	// add ourselves to active scheduler
	CActiveScheduler::Add(this);
	
	// get a session going
	User::LeaveIfError(iWs.Connect());
	
	// construct our one and only window group
	iGroup=RWindowGroup(iWs);
	User::LeaveIfError(iGroup.Construct(2,ETrue));	// meaningless handle; enable focus
	
	// construct screen device and graphics context
	iScreen=new (ELeave) CWsScreenDevice(iWs);		// make device for this session
	User::LeaveIfError(iScreen->Construct());		// and complete its construction
	User::LeaveIfError(iScreen->CreateContext(iGc));// create graphics context

	iWindow = new (ELeave) CWindow (this);
	iWindow->ConstructL(iRect);

	// Set the ordinal position to ECoeWinPriorityFep
	iGroup.SetOrdinalPosition(0, ECoeWinPriorityFep);
	// Disables receipt of focus
	iGroup.EnableReceiptOfFocus(EFalse);
	// Set the window is non-fading
	iGroup.SetNonFading(ETrue);

	// request first event and start scheduler
	IssueRequest();
}

CWsClient::~CWsClient()
{
	// neutralize us as an active object
	Deque();	// cancels and removes from scheduler
	// get rid of everything we allocated
	delete iGc;
	delete iScreen;
	delete iWindow;

	// destroy window group
	iGroup.Close();
	// finish with window server
	iWs.Close();
}

void CWsClient::IssueRequest()
{
	iWs.RedrawReady(&iStatus);	// request redraw
	SetActive();				// so we're now active
}

void CWsClient::DoCancel()
{
	iWs.RedrawReadyCancel();	// cancel redraw request
}

/****************************************************************************\
|	Function:	CWsClient::RunL()
|				Called by active scheduler when an even occurs
|	Purpose:	do Redraw
\****************************************************************************/
void CWsClient::RunL()
{
	// find out what needs to be done
	TWsRedrawEvent redrawEvent;
    iWs.GetRedraw(redrawEvent); // get event
	CWindow* window=(CWindow*)(redrawEvent.Handle()); // get window
	if (window)
	{
		TRect rect=redrawEvent.Rect();	// and rectangle that needs redrawing
		// now do drawing
		iGc->Activate(window->Window());
		window->Window().BeginRedraw(rect);
		window->Draw(rect);
		window->Window().EndRedraw();
		iGc->Deactivate();
	}
	// maintain outstanding request
	IssueRequest(); // maintain outstanding request
}


///////////////////////////////////////////////////////////////////////////////
////////////////////////// CWindow implementation /////////////////////////////
///////////////////////////////////////////////////////////////////////////////

CWindow::CWindow(CWsClient* aClient)
	: iClient(aClient)
{
}

void CWindow::ConstructL (const TRect& aRect)
{
	// Use the window group for parent window
	RWindowTreeNode* parent= &(iClient->iGroup);
	iWindow = RWindow(iClient->iWs);				// use app's session to window server
	User::LeaveIfError(iWindow.Construct(*parent,(TUint32)this));
	iRect = aRect;
	iWindow.SetExtent(iRect.iTl, iRect.Size()); // set extent relative to group coords
	iWindow.Activate();							// window is now active

	// load bitmap
	// first of all, get mbm file name
	TFileName mbmFileName;
	GetProcessPath(mbmFileName);
	mbmFileName.Append(_L("\\"));
	mbmFileName.Append(KMBMFileName);

	// load bitmap
	// for some reason we can't use EMbmLockserverRecord, EMbmLockserverRecordmask
	iBitmap = new (ELeave) CFbsBitmap();
	User::LeaveIfError(iBitmap->Load(mbmFileName, EMbmLockserverRecord));
	iBitmapMask = new (ELeave) CFbsBitmap();
	User::LeaveIfError(iBitmapMask->Load(mbmFileName, 1));
}

CWindow::~CWindow()
{
	iWindow.Close();	// close our window
	if(iBitmap)
		delete iBitmap;
	if(iBitmapMask)
		delete iBitmapMask;
}

RWindow& CWindow::Window()
{
	return iWindow;
}

CWindowGc* CWindow::SystemGc()
{
	return iClient->iGc;
}

/****************************************************************************\
|	Function:	CWindow::Draw
|	Purpose:	Redraws the contents of CSmallWindow within a given
|				rectangle.  CSmallWindow displays a square border around
|				the edges of the window, and two diagonal lines between the
|				corners.
|	Input:		aRect	Rectangle that needs redrawing
|	Output:		None
\****************************************************************************/
void CWindow::Draw(const TRect& aRect)
{
	// Drawing to a window is done using functions supplied by
	// the graphics context (CWindowGC), not the window.
	CWindowGc* gc = SystemGc(); // get a gc
	gc->SetClippingRect(aRect); // clip outside this rect
	gc->Clear(aRect);			// clear
	
	TSize tempSize = iBitmap->SizeInPixels();
	TRect sourceRect(0,0,tempSize.iWidth,tempSize.iHeight);
	gc->BitBltMasked(TPoint(0,0),iBitmap,sourceRect,iBitmapMask,ETrue);
}


// End of file